/*
 * canvas 1.0
 * A simple, canvas CanvasRenderingContext2D.prototype 原型扩展库，便于链式操作；
 * from wbh5.com @Author leiroc
 * Copyright 2015, MIT License
 *
 */


window.requestNextAnimationFrame = (function() {
    var originalWebkitRequestAnimationFrame = undefined,
        wrapper = undefined,
        callback = undefined,
        geckoVersion = 0,
        userAgent = navigator.userAgent,
        index = 0,
        self = this;

    // Workaround for Chrome 10 bug where Chrome
    // does not pass the time to the animation function

    if (window.webkitRequestAnimationFrame) {
        wrapper = function(time) {

            if (time === undefined) {
                time += new Date();
            }

            self.callback(time);
        };

        // Make the switch

        originalWebkitRequestAnimationFrame = window.webkitRequestAnimationFrame;

        window.webkitRequestAnimationFrame = function(wrapper, element) {
            self.callback = callback;

            // Browser calls the wrapper and wrapper calls the callback

            originalWebkitRequestAnimationFrame(wrapper, element);
        };
    }

    // Workaround for Gecko 2.0, which has a bug in
    // mozRequestAnimationFrame() that restricts animations
    // to 30-40 fps.

    if (window.mozRequestAnimationFrame) {
        // Check the Gecko version. Gecko is used by browsers
        // other than Firefox. Gecko 2.0 corresponds to
        // Firefox 4.0.

        index = userAgent.indexOf('rv:');

        if (userAgent.indexOf('Gecko') != -1) {
            geckoVersion = userAgent.substr(index + 3, 3);

            if (geckoVersion === '2.0') {
                // Forces the return statement to fall through
                // to the setTimeout() function.

                window.mozRequestAnimationFrame = undefined;
            }
        }
    }

    return window.requestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        window.oRequestAnimationFrame ||
        window.msRequestAnimationFrame ||

        function(callback, element) {
            var start,
                finish;

            window.setTimeout(function() {
                start = +new Date();
                callback(start);
                finish = +new Date();

                self.timeout = 1000 / 60 - (finish - start);

            }, self.timeout);
        };
})();


//停止动画
window.cancelAnimate = function(id) {
    return window.cancelAnimationFrame(id);
}

;
(function(prototype) {
    //绘制矩形
    prototype.drawRect = function(x, y, w, h, color, type) {
        //fillRect
        if (type == 'fill') {
            this.fillStyle = color + '';
            this.fillRect(x, y, w, h);
        } else if (type == 'stroke') {
            //strokeRect
            this.strokeStyle = color + '';
            this.strokeRect(x, y, w, h)
        } else if (type == 'round') {

        } else {
            alert('type 参数错误')
        }
        return this;
    }
    //清除
    prototype.clear = function(x, y, w, h) {
        this.clearRect(x, y, w, h);
        return this;
    }
    //圆角矩形
    prototype.roundRect = function(x, y, w, h, color, r, type) {
        this.beginPath();
        this.moveTo(x, y + r);
        this.lineTo(x, y + h - r);
        this.quadraticCurveTo(x, y + h, x + r, y + h);
        this.lineTo(x + w - r, y + h);
        this.quadraticCurveTo(x + w, y + h, x + w, y + h - r);
        this.lineTo(x + w, y + r);
        this.quadraticCurveTo(x + w, y, x + w - r, y);
        this.lineTo(x + r, y);
        this.quadraticCurveTo(x, y, x, y + r);
        if (type == 'fill') {
            this.fillStyle = color + '';
            this.fill();
        } else if (type == 'stroke') {
            this.strokeStyle = color + '';
            this.stroke();
            this.closePath();
        }

        return this;
    }
    //绘制圆形
    prototype._arc = function(x, y, r, sAngle, eAngle, direction, objTo, color, type) {
        //type == false, 顺时针
        this.beginPath();
        this.arc(x, y, r, sAngle, eAngle, direction);
        if (objTo) {
            this.lineTo(objTo.x, objTo.y);
        }

        if (type == 'fill') {
            this.fillStyle = color + '';
            this.fill();
        } else if (type == 'stroke') {
            this.strokeStyle = color + '';
            this.stroke();
            this.closePath();
        }
        return this;
    }
    //绘制三角形
    prototype.triangle = function(x, y, objPos, color, type) {
        this.beginPath();
        this.moveTo(x, y);
        this.lineTo(objPos.x1, objPos.y1);
        this.lineTo(objPos.x2, objPos.y2);

        if (type == 'fill') {
            this.fillStyle = color + '';
            this.fill();
        } else if (type == 'stroke') {
            this.strokeStyle = color + '';
            this.lineTo(x, y);
            this.stroke();
            this.closePath();
        }

        return this;
    }
    //绘制图片
    prototype.drawImg = function(url, x, y, w, h,callback) {
        var that = this,
            img = new Image();

        img.onload = function() {
            that.drawImage(img, x, y, w, h);
            
            
            if(callback){
            		callback();
            }
            
        }
        img.src = url;
        return this;
    }
    //线宽
    prototype.lineW = function(w) {
        this.lineWidth = w;
        return this;
    }
    //移动
    prototype.trans = function(x, y) {
        this.translate(x, y);
        return this;
    }
    //保存
    prototype._save = function() {
        this.save();
        return this;
    }
    prototype._moveTo = function(x, y) {
        this.moveTo(x, y);
        return this;
    }
    prototype._stroke = function() {
        this.stroke();
        return this;
    }
    prototype._lineTo = function(x, y) {
        this.lineTo(x, y);
        return this;
    }
    prototype.bPath = function() {
        this.beginPath();
        return this;
    }
    prototype.cPath = function() {
        this.closePath();
        return this;
    }
    prototype.sStyle = function(color) {
        this.strokeStyle = color;
        return this;
    }
    prototype.fStyle = function(color) {
        this.fillStyle = color;
        return this;
    }
    prototype._rotate = function(deg) {
        this.rotate(deg);
        return this;
    }
    prototype.sText = function(text, x, y) {
        this.strokeText(text, x, y);
        return this;
    }
    prototype.fText = function(text, x, y) {
        this.fillText(text, x, y);
        return this;
    }
    prototype._font = function(p) {
        this.font = p + 'px Arial';
        return this;
    }
    prototype._restore = function() {
        this.restore();
        return this;
    }
    prototype._scale = function(x, y) {
        this.scale(x, y);
        return this;
    }
    prototype._gco = function(str) {
        this.globalCompositeOperation = str;
        return this;
    }
    prototype._lineJoin = function(str) {
        this.lineJoin = str;
        return this;
    }
    prototype._lineCap = function(str) {
        this.lineCap = str;
        return this;
    }
})(CanvasRenderingContext2D.prototype);


/*
 * wipe 1.0
 * A simple, efficent mobile wipe(简单的移动端涂抹插件)
 * from wbh5.com @Author leiroc
 * Copyright 2015, MIT License
 *
*/

/**
 * animation parmas:
 *
 * @param {Element}      el         canvas 外层元素
 * @param {String}       fg         涂抹层（可以使图片{.png|.jpg}，和16进制颜色 #ccc）
 * @param {Number}       size       涂抹笔直径
 * @param {Boolean}      debug      显示控制数据输出，true时，会在控制台输出轨迹数据
 * @param {Boolean}      autoWipe   是否自动播放
 * @param {Array}        data       自动播放的数据
 * @param {Function}     onswiping  涂抹时的回调函数
 */

function Wipe(opts) {
	this.opts = {
        el: '#wipe',
        fg: '#ccc',
        size: 10,
		color:"#000000",
        debug: false,
        autoWipe: false,
        data: [],
        imgWidth:100,
        imgHeight:100,
        
        lineMax : 30,		//笔画最大粗
	    lineMin : 3, 		//笔画最小粗
	    linePressure : 1,  	//按住多长时间达到最大线粗
	    smoothness : 80,
        
        
        onswiping: function(percent, data) {}
   	};
   	for (var i in opts) {
        this.opts[i] = opts[i]
    }
   	
	this.init(opts);
};

Wipe.prototype = {
    calcDistance: function(loc1, loc2) { // 前后两点间的路程
        return Math.sqrt((loc1.x - loc2.x) * (loc1.x - loc2.x) 
            + (loc1.y - loc2.y) * (loc1.y - loc2.y))
    },
    getXY : function (e){ 
	    return {  
	        x : e.touches[0].pageX - this.canvas.offsetLeft + (document.body.scrollLeft || document.documentElement.scrollLeft),  
	        y : e.touches[0].pageY - this.canvas.offsetTop  + (document.body.scrollTop || document.documentElement.scrollTop)  
	    }  
	},
    doc: document,
    $: function(name) {
        return this.doc.querySelector(name);
    },
    init: function(opts) {
    	
        var self = this,
            devicePixelRatio = window.devicePixelRatio || 1;
        this.devicePixelRatio = devicePixelRatio;
        //insert canvas el
        this.wrap = this.$(this.opts.el);
        //clear html
        this.wrap.innerHTML = null;
        this.wrap.appendChild(this.doc.createElement('canvas'));
//      this.wrapWidth = parseInt(this.wrap.offsetWidth);
//      this.wrapHeight = parseInt(this.wrap.offsetHeight);
        this.wrapWidth = this.opts.imgWidth;
        this.wrapHeight = this.opts.imgHeight;
        
        //prevent defalut
        this.wrap.addEventListener('touchmove', function(e) {
            e.preventDefault()
        });
        //get canvas
        this.canvas = this.wrap.childNodes[0];
        this.canvas.style.cssText += 'width: 100%; height: 100%';
        this.ctx = this.canvas.getContext('2d');
        //set attr
        this.canvas.setAttribute('width', this.wrapWidth * devicePixelRatio);
        this.canvas.setAttribute('height', this.wrapHeight * devicePixelRatio);
        //get width & height
        this.cWidth = this.canvas.width;
        this.cHeight = this.canvas.height;
        //canvas context scale
        this.ctx.scale(devicePixelRatio, devicePixelRatio);
        //pixels
        this.pixels = Math.floor(this.cWidth * this.cHeight);
        //drawFg
        this.drawFg();
        //set Event
        this.setEvent();
        // auto wipe
        if (this.opts.autoWipe) {
            setTimeout(function() {
                self.autoWipe();
            }, 100)
        }
        //path
        this.path = [];
        
	    this.ctx.fillStyle = this.opts.color;  
        
        //宝哥哥改写
       	//新增模仿毛笔效果
	    this.moveFlag = false;  
	    this.upof = {};  
	    this.radius = 0;  
	    this.has = [];  
	    this.lineMax = 30;  
	    this.lineMin = 3;  
	    this.linePressure = 1;  
	    this.smoothness = 80;  
	     
    },
    reset: function (fg) {
    		
        this.ctx._gco('source-over');
        this.drawFg(fg);
        //path
        this.path = [];
    },
    winTcanvasXY: function (canvas, x, y) {
        var cC = canvas.getBoundingClientRect();
        return {
            x: x - cC.left,
            y: y - cC.top
        }
    },
    clear: function() {
    	
		userScore = 0;//初始化分数
		bg_mask_opacity = .2;//初始化背景亮度
		bg_mask.css("opacity",bg_mask_opacity);
		
        this.ctx.clear(0, 0, this.cWidth, this.cHeight);
    },
    saveImg:function(callback){
    		//把外边框加上去
//  		this.ctx.drawImg("../images/canvas/zi1_kuang.png",0,0,this.opts.imgWidth, this.opts.imgHeight,function(){
//  			var img = new Image();
//	        img.onload = function(){
//	            $("body").append(img);
//	        }
//	        img.src = this.canvas.toDataURL();
//  		}.bind(this));
    		var img = new Image();
        img.onload = function(){
//          $("body").append(img);
			wipe.wrap.innerHTML="";
			img.setAttribute("width",580);
			img.setAttribute("height",580);
            wipe.wrap.appendChild(img);
            $("#zi_bg").hide();
            callback(base64);
        }
        var base64  = this.canvas.toDataURL();
        img.src = base64
    },
    
   drawFg: function(fg) {
   		
   		var _s = this;
        if (this.opts.fg || fg) {
            //fixed wipe_img bug
            if (this.opts.fg.charAt(0) === '#' || (fg && fg.charAt(0) === '#')) {
                this.ctx.drawRect(0, 0, this.cWidth, this.cHeight, this.opts.fg || fg, 'fill');
            } else if (/png|jpg|jpeg|svg/.test(this.opts.fg)) {
                //draw bg img
//              this.ctx.drawImg(this.opts.fg, 0, 0, this.wrapWidth, this.wrapHeight);

				this.ctx.drawImg(this.opts.fg,0,0, this.opts.imgWidth, this.opts.imgHeight,function(){
					wipe.getCanvasImgData();
					wipe.getOverWenziImgData();//获取当前在画布所画的文字像素数据
					if(_s.opts.callback){
						_s.opts.callback();
					}
				});
            }
        }
    },
    wipeStart: function(e) {
    		var ctx = this.ctx;
    		var self = this;
        if (e == undefined) return;
        self.startTime = +new Date; //start time
        var x, y;
        if (self.opts.autoWipe) {
            x = e.x;
            y = e.y;
        } else {
            var xy = self.winTcanvasXY(self.canvas, e.touches[0].pageX, e.touches[0].pageY);
            x = xy.x;
            y = xy.y;
            if (self.startTime + 20 * 1000 < self.endTime) {
                self.path = [];
            } else {
                self.path.push('pause');
                self.path.push(xy);//第一个点也需要添加到路径里面
            } 
        }

		
    		//添加毛笔效果
   		 this.moveFlag = true;  
	    this.has = [];  
	    this.upof = {x:x,y:y};  
	    this.has.unshift({time:new Date().getTime() ,dis:0});  
	    
//	     ctx._gco('source-over')._lineJoin('round')._lineCap('round')
//          .sStyle(this.opts.color).lineW(this.opts.size);
            
        startT();//开启定时器
        
    },
    wipeMove: function( e) {
    		
    		var ctx = this.ctx;
    		var self = this;
        var x, y;
        if (e == undefined) return;
        if (self.opts.autoWipe) {
            x = e.x;
            y = e.y;
        } else {
            var xy = self.winTcanvasXY(self.canvas, e.touches[0].pageX, e.touches[0].pageY);
            x = xy.x;
            y = xy.y;
            //catch data
            self.path.push(xy);
        }
//      ctx._lineTo(x, y)._stroke();
        
        //增加毛笔效果
//      if (!this.moveFlag)  
//	        return;  
	    var of = {x:x,y:y};  
	    var up = this.upof;  
	    var ur = this.radius;  
	    this.has.unshift({time:new Date().getTime() ,dis:this.calcDistance(up,of)});  
	    var dis = 0;  
	    var time = 0;
	    for (var n = 0; n < this.has.length-1; n++) {  
	        dis += this.has[n].dis;  
	        time += this.has[n].time-this.has[n+1].time; 
	        if (dis>this.smoothness)  
	            break;  
	    }  
//	 time= time? time: 3;
	    var or = Math.min(time/dis*this.linePressure+this.lineMin , this.lineMax) / 2;  
	    this.radius = or;  
	    this.upof = of;  
//	    if (this.has.length<=4)  
//	        return;  
	    var len = Math.round(this.has[0].dis/2)+1;  
	    for (var i = 0; i < len; i++) {  
	        var x = up.x + (of.x-up.x)/len*i;  
	        var y = up.y + (of.y-up.y)/len*i;  
	        var r = ur + (or-ur)/len*i;  
	        this.ctx.beginPath();  
	        this.ctx.arc(x,y,r,0,2*Math.PI,true);  
	        this.ctx.fill();  
	    }  
    },
    wipeEnd: function( e) {
    	
    		var ctx = this.ctx;
    		var self = this;
        self.endTime = +new Date; //end time
        ctx.cPath();
//      self.opts.onswiping.call(self, self.getPercent(), JSON.stringify(self.path),JSON.stringify(self.path.slice(self.path.lastIndexOf('pause'))));
//      self.opts.debug && console.log(JSON.stringify(self.path));
        
        //添加毛笔效果
        this.moveFlag = false;  
        
        //关闭定时器
         endT();//定时器
    },
    setEvent: function() {
        var self = this,
            ctx = this.ctx;
		
        this.canvas.addEventListener('touchstart', function(e) {
            self.wipeStart(e);
        });
        this.canvas.addEventListener('touchmove', function(e) {
            self.wipeMove( e);
        });
        this.canvas.addEventListener('touchend', function(e) {
            self.wipeEnd(e);
        });
    },
        /**
     *获取用户分数
     * 根据(正确涂画像素点-错误涂画像素点）/ 应涂的总像素点 *100  得到百分制分数 
     */
    getPercent:function(callback){
    		//local img will be error ,so use try
        try {
            var self  = this;
            var hits = 0,
                imgData = self.ctx.getImageData(0, 0, self.cWidth, self.cHeight);
               
			var originImgData = self.originImgData;
			
			var jian=0;
            for (var i = 0, len = imgData.data.length; i < len; i += 4) {
				if((imgData.data[i]===34&& imgData.data[i + 1] === 23 &&imgData.data[i + 2] === 20&& imgData.data[i + 3] === 255)&&
                    (originImgData.data[i]===0&& originImgData.data[i + 1] === 0 &&originImgData.data[i + 2] === 0&& originImgData.data[i + 3] === 3)
               ){
               		//加分
               		hits++;
				}else if((imgData.data[i]===34&& imgData.data[i + 1] === 23 &&imgData.data[i + 2] === 20&& imgData.data[i + 3] === 255)&&
                    (originImgData.data[i]===0&& originImgData.data[i + 1] === 0 &&originImgData.data[i + 2] === 0&& originImgData.data[i + 3] === 0)){
					//减分						
					jian++;
				}


            }
            
//          console.log("hits"+hits);
//          console.log("jian"+jian);
//          console.log("self.ziOriginImgDataCount"+self.ziOriginImgDataCount);
			if(hits==0){
				totalSource = 0;
			}else{
				 totalSource = parseInt((hits-jian)/self.ziOriginImgDataCount*100+Math.random()*20+15);
			}
			totalSource = totalSource>=100?100:totalSource;
           
            if(callback){
            		callback(totalSource);
            }
            return totalSource;
        } catch (e) {
            console.log(e)
        }
    },
    
    /*获取原始画布上的所有像素
     * 
     * 
     * @reuturn imageData
     */
    getCanvasImgData: function() {
        try {
        		
			//原图的所有像素
          	this.originImgData = this.ctx.getImageData(0, 0, this.cWidth, this.cHeight);
          	
        } catch (e) {
            console.log(e)
        }
    },
     /*获取画布上的画的文字的所有像素
     * 
     * 
     * @reuturn imageData
     */
    getOverWenziImgData: function() {
        try {
        	
          	//文字的所有像素
          	this.ziOriginImgDataCount=0;
          	for (var i = 0, len =this.originImgData.data.length; i < len; i += 4) {
          		if(this.originImgData.data[i]===0&& this.originImgData.data[i + 1] === 0 &&this.originImgData.data[i + 2] === 0&& this.originImgData.data[i + 3] === 3){
               		//加分
               		this.ziOriginImgDataCount++;
				}
          	}
          	
        } catch (e) {
            console.log(e)
        }
    },
    
    //根据笔画路径判断相似度
    similar: function (datasFist, datasSecond) {
        var fLen = datasFist.length,
            sLen = datasSecond.length,
            si = 0;

        for (var i = 0; i < fLen; i++) {
            if (datasFist[i].x == datasSecond[i].x || datasFist[i].x <= datasSecond[i].x + 1 || datasFist[i].x <= datasSecond[i].x - 1) {
                if (datasFist[i].y == datasSecond[i].y || datasFist[i].y <= datasSecond[i].y + 1 || datasFist[i].y<= datasSecond[i].y - 1) {
                    si ++;
                }
            }
        }
        return Math.floor(si / fLen * 100);
    },
   
   //自动播放
    autoWipe: function(datas) {
        var self = this,
            ctx = this.ctx,
            data = datas || self.opts.data,
            len = data.length,
            i = 0,
            animID;
        data.forEach(function(v){self.path.push(v)});//将自动涂抹的data也加入到自身的path中，可以完整的还原

        function animate() {
            i++;//外面已经调用了一次wipeStart，索引可以直接++ 从下一个开始
            //start animation
            animID = requestNextAnimationFrame(animate);

            if (data[i] === 'pause') {
                self.wipeEnd(ctx, data[i], self);
                ++i<len?self.wipeStart(ctx, data[i], self):cancelAnimate(animID);//如果pause后面有数据则从后面的开始，如果没有则直接停止
            } else if (i<len){
                self.wipeMove(ctx, data[i], self);
            } else if (i >= len - 1) {
                cancelAnimate(animID);
                //end
                self.wipeEnd(ctx, data[len - 1], self);
            }
        }

        //sart  如果数据的前面是pause 则直接跳过第一个pause从第一个有效数据开始
        while(i<len&&data[i]==='pause') i++;
        //跳过数据前面的pause后如果数还有数据则正常开始否则不用开始涂抹
        if(i<len){
            self.wipeStart(ctx,data[i], self);
            //move
            requestNextAnimationFrame(animate);
        }
    }

    

}
